<template>
  <div class="json-editor-container" :style="{ height: finalHeight }">
    <div ref="editor" class="json-editor"></div>
    <div v-if="error" class="error-message">{{ error }}</div>
  </div>
</template>

<script>
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'
import 'monaco-editor/esm/vs/language/json/monaco.contribution'


export default {
  name: 'JsonEditor',
  props: {
    value: {
      type: String,
      default: '{}'
    },
    height: {
      type: [String, Number],
      default: '400px'
    },
    minHeight: {
      type: [String, Number],
      default: '300px'
    },
    maxHeight: {
      type: [String, Number],
      default: null
    },
    readOnly: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      editor: null,
      error: null
    }
  },
  watch: {
    value(newVal) {
      if (this.editor && this.editor.getValue() !== newVal) {
        this.editor.setValue(newVal)
      }
    },
    height(newHeight) {
      if (this.editor) {
        this.editor.layout({
          height: this.$el.offsetHeight,
          width: this.$el.offsetWidth
        })
      }
    }
  },
  mounted() {
    this.initEditor()
  },
  beforeDestroy() {
    if (this.editor) {
      this.editor.dispose()
    }
  },
  computed: {
    finalHeight() {
      if (typeof this.height === 'number') {
        return `${this.height}px`
      }
      return this.height
    },
    finalMinHeight() {
      if (typeof this.minHeight === 'number') {
        return `${this.minHeight}px`
      }
      return this.minHeight
    },
    finalMaxHeight() {
      if (!this.maxHeight) return 'none'
      if (typeof this.maxHeight === 'number') {
        return `${this.maxHeight}px`
      }
      return this.maxHeight
    }
  },
  methods: {
    initEditor() {
      try {
        // 初始化编辑器
        this.editor = monaco.editor.create(this.$refs.editor, {
          value: this.value,
          language: 'json',
          theme: 'vs',
          automaticLayout: true,
          scrollBeyondLastLine: false,
          minimap: {
            enabled: false
          },
          readOnly: this.readOnly,
          lineNumbers: 'on',
          roundedSelection: true,
          scrollbar: {
            vertical: 'auto',
            horizontal: 'auto'
          },
          tabSize: 2,
          formatOnPaste: true,
          formatOnType: true
        })

        // 监听内容变化
        this.editor.onDidChangeModelContent(() => {
          const value = this.editor.getValue()
          this.$emit('input', value)
          this.validateJson(value)
        })

        // 初始验证
        this.validateJson(this.value)

        // 设置高度
        this.$nextTick(() => {
          this.editor.layout({
            height: this.$el.offsetHeight,
            width: this.$el.offsetWidth
          })
        })
      } catch (error) {
        console.error('Failed to initialize Monaco Editor:', error)
      }
    },
    validateJson(json) {
      try {
        if (json) {
          JSON.parse(json)
          this.error = null
          this.$emit('valid', true)
        } else {
          this.error = 'JSON 不能为空'
          this.$emit('valid', false)
        }
      } catch (e) {
        this.error = `JSON 格式错误: ${e.message}`
        this.$emit('valid', false)
      }
    },
    formatJson() {
      try {
        const json = JSON.parse(this.editor.getValue())
        const formatted = JSON.stringify(json, null, 2)
        this.editor.setValue(formatted)
        this.error = null
        this.$emit('valid', true)
      } catch (e) {
        this.error = `无法格式化: ${e.message}`
        this.$emit('valid', false)
      }
    },
    setContent(content) {
      if (this.editor) {
        this.editor.setValue(content)
      }
    }
  }
}
</script>

<style scoped>
.json-editor-container {
  position: relative;
  width: 100%;
  height: v-bind(finalHeight);
  min-height: v-bind(finalMinHeight);
  max-height: v-bind(finalMaxHeight);
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.json-editor {
  flex: 1;
  width: 100%;
  min-height: 200px; /* 确保即使内容少也有足够高度 */
}

.error-message {
  flex-shrink: 0;
  color: #f56c6c;
  font-size: 12px;
  padding: 5px;
  background-color: #fef0f0;
  border-top: 1px solid #fde2e2;
}
</style>
